import { Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { MenuService } from '../menu/menu.service'
import { FindOptionsWhere, In, Like, Not, Repository } from 'typeorm'
import { ApiException, AuthEnum, AuthRolePermissionDTO, CreateRoleDTO, RoleEntity, UpdateRoleDTO } from '@/common'

@Injectable()
export class RoleService {
  constructor(private readonly menuService: MenuService, @InjectRepository(RoleEntity) private readonly roleRepository: Repository<RoleEntity>) {}

  /** 新增角色 */
  public async create(createDto: CreateRoleDTO): Promise<string> {
    const role = await this.roleRepository.findOneBy({ code: createDto.code })
    if (role) throw new ApiException(`角色 ${createDto.code} 已存在`)
    await this.roleRepository.save(createDto)
    return '添加成功'
  }

  /** 根据传入 id 组删除单个或者多个数据 */
  public async delete(roleIds: string[]) {
    const containsAdmin = roleIds.includes(AuthEnum.ADMIN_ROLE_ID)
    if (containsAdmin) throw new ApiException(`管理员角色无法被删除`)
    return this.roleRepository.delete(roleIds)
  }

  /** 更新角色信息 */
  public async update(updateDto: UpdateRoleDTO): Promise<string> {
    if (updateDto.code && updateDto.code.toLowerCase() === AuthEnum.ADMIN_ROLE_CODE) throw new ApiException(`管理员角色数据禁止被修改`)
    await this.roleRepository.save(updateDto)
    return '更新成功'
  }

  /** 授权角色菜单权限 */
  public async authPermission(authDto: AuthRolePermissionDTO) {
    const role = await this.findOneById(authDto.roleId)
    role.menus = await this.menuService.findManyByIds(authDto.menuIds)
    await this.update(role)
    return '授权成功'
  }

  /** 查询角色分页列表 */
  public async findList(queryParams: TableQueryParams<RoleEntity>) {
    const { code, name, remark, status, take, skip } = queryParams
    const queryBuilder = this.roleRepository.createQueryBuilder('role')
    const keys: (keyof RoleEntity)[] = ['id', 'code', 'status', 'name', 'level', 'createTime', 'updateTime', 'createBy', 'updateBy']
    queryBuilder.select(keys.map((key) => `role.${key}`))
    const where: FindOptionsWhere<RoleEntity> = {}
    if (code) where.code = Like(`%${code}%`)
    if (code) where.name = Like(`%${name}%`)
    if (code) where.remark = Like(`%${remark}%`)
    if (status) where.status = +status
    queryBuilder.orderBy('role.createTime', 'ASC') // 排序
    queryBuilder.skip(skip).take(take) // 分页
    const [records, total] = await queryBuilder.getManyAndCount() //  一次性获取数据和总数
    return { total, records }
  }

  /** 查询角色不分页列表 */
  public async findAll() {
    const where: FindOptionsWhere<RoleEntity> = { status: 1 }
    return this.roleRepository.find({ where, order: { createTime: 'ASC' } })
  }

  /** 根据角色 ID 查找其详情 */
  public async findOneById(roleId: string) {
    const where: FindOptionsWhere<RoleEntity> = { id: roleId }
    const role = await this.roleRepository.findOne({ where, relations: { menus: true } })
    if (!role) throw new ApiException(`该角色不存在`)
    return role
  }

  /** 根据角色 ID 组查询多条角色数据 */
  public async findManyByIds(roleIds: string[]) {
    const where: FindOptionsWhere<RoleEntity> = { id: In(roleIds) }
    return this.roleRepository.find({ where, order: { createTime: 'ASC' } })
  }
}
